package com.sihan.framework.etm.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.sihan.framework.etm.common.websocket.WebSocketUtil;
import com.sihan.framework.etm.entity.User;
import com.sihan.framework.etm.mapper.OrgMapper;
import com.sihan.framework.etm.mapper.UserMapper;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.framework.model.ApiResult;
import com.framework.mybatis.Condition;
import com.framework.util.JsonUtils;
import com.framework.util.WebUtils;
import com.sihan.framework.etm.common.util.DateUtils;
import com.sihan.framework.etm.common.util.ImgUtils;
import com.sihan.framework.etm.dto.BoxDeviceInfoDTO;
import com.sihan.framework.etm.dto.DeviceLightCommandDTO;
import com.sihan.framework.etm.dto.ExternalJsonObjectDTO;
import com.sihan.framework.etm.dto.SetDeviceConfigDTO;
import com.sihan.framework.etm.dto.business.BorrowToolTaskDTO;
import com.sihan.framework.etm.dto.business.DeviceWarehouseDTO;
import com.sihan.framework.etm.entity.baseData.DeviceModel;
import com.sihan.framework.etm.entity.baseData.DeviceStateModel;
import com.sihan.framework.etm.entity.baseData.ToolModel;
import com.sihan.framework.etm.entity.business.StationLacation;
import com.sihan.framework.etm.entity.business.ToolBorrowDetail;
import com.sihan.framework.etm.entity.business.ToolBorrowMaster;
import com.sihan.framework.etm.entity.business.ToolBorrowPlanMaster;
import com.sihan.framework.etm.entity.business.ToolBorrowReturnRecord;
import com.sihan.framework.etm.entity.business.ToolInWarehouseMaster;
import com.sihan.framework.etm.entity.business.ToolInWarehouseRecord;
import com.sihan.framework.etm.entity.business.ToolInspectDetail;
import com.sihan.framework.etm.entity.business.ToolInspectInDetail;
import com.sihan.framework.etm.entity.business.ToolInspectInMaster;
import com.sihan.framework.etm.entity.business.ToolInspectMaster;
import com.sihan.framework.etm.entity.business.ToolReturnDetail;
import com.sihan.framework.etm.entity.business.ToolReturnMaster;
import com.sihan.framework.etm.entity.business.ToolRunning;
import com.sihan.framework.etm.entity.business.ToolWarehouseDetail;
import com.sihan.framework.etm.entity.business.ToolWarehouseMaster;
import com.sihan.framework.etm.enums.CacheKeyName;
import com.sihan.framework.etm.enums.FormatImgPre;
import com.sihan.framework.etm.enums.MqttSendCommandFunc;
import com.sihan.framework.etm.enums.OperateType;
import com.sihan.framework.etm.mapper.CommonMapper;
import com.sihan.framework.etm.mapper.baseData.DeviceMapper;
import com.sihan.framework.etm.mapper.baseData.DeviceStateMapper;
import com.sihan.framework.etm.mapper.baseData.ToolMapper;
import com.sihan.framework.etm.mapper.business.InspectDetailMapper;
import com.sihan.framework.etm.mapper.business.InspectInDetailMapper;
import com.sihan.framework.etm.mapper.business.InspectInMasterMapper;
import com.sihan.framework.etm.mapper.business.InspectMasterMapper;
import com.sihan.framework.etm.mapper.business.StationLocationMapper;
import com.sihan.framework.etm.mapper.business.DeviceRunningMapper;
import com.sihan.framework.etm.mapper.business.ToolBorrowDetailMapper;
import com.sihan.framework.etm.mapper.business.ToolBorrowMapper;
import com.sihan.framework.etm.mapper.business.ToolBorrowMasterMapper;
import com.sihan.framework.etm.mapper.business.ToolBorrowPlanMasterMapper;
import com.sihan.framework.etm.mapper.business.ToolBorrowReturnRecordMapper;
import com.sihan.framework.etm.mapper.business.ToolInWarehouseMasterMapper;
import com.sihan.framework.etm.mapper.business.ToolInWarehouseRecordMapper;
import com.sihan.framework.etm.mapper.business.ToolReturnDetailMapper;
import com.sihan.framework.etm.mapper.business.ToolReturnMasterMapper;
import com.sihan.framework.etm.schema.master.BorrowReturnRecordSchema;
import com.sihan.framework.etm.schema.master.InspectRecordSchema;
import com.sihan.framework.etm.service.CodeService;
import com.sihan.framework.etm.service.baseData.DeviceService;
import com.sihan.framework.etm.vo.business.BorrowDetailVO;
import com.sihan.framework.etm.vo.business.BorrowPlanVO;
import com.sihan.framework.etm.vo.business.CacheOcrModel;
import com.sihan.framework.etm.vo.business.DeviceToolTypeVO;
import com.sihan.framework.etm.vo.schema.DeviceRunningStateSchema;
import com.sihan.framework.etm.vo.schema.DeviceStatisticsToolTypeResultSchema;
import com.sihan.framework.etm.vo.schema.ToolTypeStatisticsSchema;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class CommonBiz {
	
	protected final static String COMMAND_HEARTBEAT = "heartbeat";//心跳
	protected final static String COMMAND_FEEDBACK = "feedback";//反馈
	protected final static Double EARTH_RADIUS = 6378.137;//地球半径
	protected final static Map<String,Integer> deviceResetTimes = new HashMap<String,Integer>();
	public Boolean doing = false;

	@Autowired
	private ImgUtils imgUtils;
	
	@Autowired
	private AppConfiguration appConfig;
	
	@Autowired
	private ToolMapper toolMapper;

	@Autowired
	private OrgMapper orgMapper;
	
	@Autowired
	private ToolBorrowMasterMapper toolBorrowMasterMapper;
	
	@Autowired
	private DeviceMapper deviceMapper;
	
	@Autowired
	private ToolBorrowDetailMapper toolBorrowDetailMapper;
	
	@Autowired
	private ToolReturnMasterMapper toolReturnMasterMapper;
	
	@Autowired
	private ToolReturnDetailMapper toolReturnDetailMapper;
	
	@Autowired
	private ToolBorrowMapper toolBorrowMapper;
	
	@Autowired
	private DeviceRunningMapper deviceRunningMapper;
	
	@Autowired
	private DeviceService deviceService;

	@Autowired
	private UserMapper userMapper;
	
	@Autowired
	private RestBiz restBiz;
	
	@Autowired
	private DeviceStateMapper deviceStateMapper;

	@Autowired
	private WebSocketUtil webSocketUtil;
	
	@Autowired
	private InspectMasterMapper inspectMasterMapper;
	
	@Autowired
	private InspectDetailMapper inspectDetailMapper;
	
	@Autowired
	private InspectInDetailMapper inspectInDetailMapper;
	
	@Autowired
	private InspectInMasterMapper inspectInMasterMapper;
	
	@Autowired
	private ToolInWarehouseMasterMapper toolInWarehouseMasterMapper;
	
	@Autowired
	private ToolInWarehouseRecordMapper toolInWarehouseRecordMapper;
	
	@Autowired
	private ToolBorrowReturnRecordMapper toolBorrowReturnRecordMapper;
	
	@Autowired
	private StationLocationMapper stationLocationMapper;
	
	@Autowired
	private ToolBorrowPlanMasterMapper toolBorrowPlanMasterMapper;
	
	@Autowired
	private CommonMapper commonMapper;
	
	@Autowired
	private CodeService codeService;
	
	public static final Object lock = new Object();
	
	protected static final Queue<String> queue = new LinkedList<String>();
	
	
	public synchronized List<String> genarateToolCode(String identify,Integer nums) {
		List<String> result = new ArrayList<String>();
		String companyCode = "022";
		String companyBusiness = "011";
		List<Map<String, Object>> codeMap = codeService.getCodeByType(
				CacheKeyName.TOOL_SERALIZE_CODE_TYPE.getValue());
		Long serialize = Long.parseLong(codeMap.get(0).get("id").toString());
		for(int i=0; i<nums; i++) {
			serialize +=1;
			String flex21Code = companyCode+companyBusiness+identify+
					String.format("%09d", serialize);
			String identifyWeight = "313131313131313131313131";
			char[] flex21CodeArray = flex21Code.toCharArray();
			char[] identifyWeightArray = identifyWeight.toCharArray();
			int sum = 0;
			for(int j=0;j<flex21CodeArray.length;j++) {
				sum += Integer.parseInt(String.valueOf(flex21CodeArray[j]))*
						Integer.parseInt(String.valueOf(identifyWeightArray[j]));
			}
			int validateCode = 10 - sum%10;
			String rfid = flex21Code+validateCode;
			result.add(rfid.substring(0, 24));
		}
		//更新初始值
		codeService.updateCode(CacheKeyName.TOOL_SERALIZE_CODE_TYPE.getValue(), serialize);
		return result;
	}

	
	/**
	 * 
	 * @description 统计工器具类型和数量
	 * @return
	 * @auther 韩兵
	 * @Date 2020年7月30日
	 * @return DeviceStatisticsToolTypeResultSchema
	 */
	public List<ToolTypeStatisticsSchema> statisticsDeviceTools(String code) {
		if(!StringUtils.isBlank(code)) {
			List<ToolTypeStatisticsSchema> existWarehouse = toolMapper.
					listDeviceWarehouseToolTypeStatistics(Arrays.asList(code.split(",")));
			if(null != existWarehouse && !existWarehouse.isEmpty()) {
				existWarehouse.stream().forEach(type->{
					type.setImg(imgUtils.formatImgPath(FormatImgPre.PRE_TOOL.getValue()+type.getImg()));
				});
			}
			return existWarehouse;
		}
		return null;
	}
	
	/**
	 * 
	 * @description  根据类型编号，返回类型名称和图片地址
	 * @param code
	 * @return
	 * @auther 韩兵
	 * @Date 2020年8月25日
	 * @return List<ToolTypeStatisticsSchema>
	 */
	public List<ToolTypeStatisticsSchema> statisticsDeviceToolTypes(String code) {
		if(!StringUtils.isBlank(code)) {
			List<ToolTypeStatisticsSchema> existWarehouse = toolMapper.
					listDeviceWarehouseToolType(Arrays.asList(code.split(",")));
			if(null != existWarehouse && !existWarehouse.isEmpty()) {
				existWarehouse.stream().forEach(type->{
					type.setImg(imgUtils.formatImgPath(FormatImgPre.PRE_TOOL.getValue()+type.getImg()));
				});
			}
			return existWarehouse;
		}
		return null;
	}
	
	/**
	 * 
	 * @description  处理关闭柜门时的数据(1:领用出库,2:领用入库,3:检验出库,4:检验入库，5：检查,6:新增入库)
	 * @param deviceWarehouse
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	public DeviceStatisticsToolTypeResultSchema receiveDeviceDatas(DeviceWarehouseDTO deviceWarehouse) {
		DeviceStatisticsToolTypeResultSchema result = new DeviceStatisticsToolTypeResultSchema();
		synchronized (lock) {
			//生成库存记录
			produceAllToolRecordByDeviceClosed(deviceWarehouse);
			//获取目前所做的操作
			Integer operateType = (Integer)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_OPERATE_TYPE.getValue(), 0);
			switch(operateType) {
				case 1: 
					checkEveryShutDownBorrowTool(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					//记录到表
					produceInOutSignleDeviceWarehouseRecord(deviceWarehouse.getDeviceCode(),
							deviceWarehouse.getDownCodes(),deviceWarehouse.getUpCodes());
					//websocket
					webSocketUtil.sendMsgForBorrow();
					break;
				case 2: 
					checkEveryShutDownBorrowReturnTool(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					//记录到表
					produceInOutSignleDeviceWarehouseRecord(deviceWarehouse.getDeviceCode(),
							deviceWarehouse.getDownCodes(),deviceWarehouse.getUpCodes());
					//websocket
					webSocketUtil.sendMsgForBorrowReturn();
					break;
				case 3: 
					checkEveryShutDownInspectOut(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					//websocket
					webSocketUtil.sendMsgForInspectOut();
					break;
				case 4: 
					checkEveryShutDownInspectIn(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					//websocket
					webSocketUtil.sendMsgForInspectIn();
					break;
				case 5: 
					checkEveryShutDownInCheck(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					break;
				case 6: 
					checkEveryShutDownAddNewTool(deviceWarehouse.getToolCodes(),deviceWarehouse.getUpCodes()
							,deviceWarehouse.getDownCodes(),deviceWarehouse.getDeviceCode());
					break;
			}
		}

		return result;
	}
	
	/**
	 * 
	 * @description  领用-每次关闭柜子时
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	@Transactional
	public void checkEveryShutDownBorrowTool(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			if(null != in && !in.isEmpty()) {
				String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
				List<BorrowDetailVO> result = toolBorrowMapper.selectBorrowDetailByPlanId(masterId);
				List<String> needDeleteCodes = new ArrayList<String>();
				if(null != result && !result.isEmpty()) {
					for(BorrowDetailVO vo : result) {
						for(String toolCode : in) {
							if(vo.getToolCode().equals(toolCode)) {
								needDeleteCodes.add(vo.getToolCode());
								break;
							}
						}
					}
				}
				
				//有值说明可能是从一个柜子转移到另一个柜子
				//那么删除这些工器具的借据明显
				if(!needDeleteCodes.isEmpty()) {
					toolBorrowMapper.deleteBorrowDetailByToolCodesAndMasterId(needDeleteCodes,masterId);
				}
				
				//如果还有工器具不在借据之内，可能就是之前借的，那么生成一个还的记录
				if(in.size() > needDeleteCodes.size()) {
					in.removeAll(needDeleteCodes);
					ToolReturnMaster master = new ToolReturnMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolReturnMasterMapper.insert(master);
					@SuppressWarnings("unchecked")
					DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
					List<ToolModel> tools = new ArrayList<ToolModel>();
					for(String toolCode : in) {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							tool.setUseRecordStatus(2);
							tool.setDeviceId(device.getId());
							toolMapper.updateById(tool);
							tools.add(tool);
							ToolReturnDetail detail = new ToolReturnDetail();
							detail.setMasterId(master.getId());
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setToolId(tool.getId());
							toolReturnDetailMapper.insert(detail);
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-领使用-入");
						}
						//发送消息到主站
						//commonSendInfo.sendToolInfoToMaster(tools);
					}
					toolBorrowMapper.updateToolBorrowHasReturn(master.getId(),
							(String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null),
							device.getId());
				}
			}
		}
	}
	
	/**
	 * 
	 * @description 领用还-每次关闭柜子时
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	@Transactional
	public void checkEveryShutDownBorrowReturnTool(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			if(null != out && !out.isEmpty()) {
				String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
				@SuppressWarnings("unchecked")
				List<ToolReturnDetail> result = toolReturnDetailMapper.selectList(new Condition<ToolReturnDetail>().eq("master_id", masterId));
				List<String> needDeleteCodes = new ArrayList<String>();
				if(null != result && !result.isEmpty()) {
					for(String toolCode : out) {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							ToolReturnDetail find = null;
							for(ToolReturnDetail vo : result) {
								if(null != vo.getToolId() && vo.getToolId().equals(tool.getId())) {
									needDeleteCodes.add(toolCode);
									find = vo;
									break;
								}
							}
							if(null != find) {
								toolReturnDetailMapper.deleteById(find.getId());
							}
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-领使用-入");
						}
					}
				}
				
				//如果还有工器具不在还据之内，那么生成一个借的记录
				if(out.size() > needDeleteCodes.size()) {
					out.removeAll(needDeleteCodes);
					ToolBorrowMaster master = new ToolBorrowMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolBorrowMasterMapper.insert(master);
					@SuppressWarnings("unchecked")
					DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
					List<ToolModel> tools = new ArrayList<ToolModel>();
					for(String toolCode : out) {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							tool.setUseRecordStatus(0);
							toolMapper.updateById(tool);
							tools.add(tool);
							ToolBorrowDetail detail = new ToolBorrowDetail();
							detail.setMasterId(masterId);
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setExpiredTime(tool.getExpiredDate());
							detail.setHasReturn(0);
							detail.setToolId(tool.getId());
							toolBorrowDetailMapper.insert(detail);
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-领使用-还-入");
						}
						//发送消息到主站
						//commonSendInfo.sendToolInfoToMaster(tools);
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @description  检验出库-每次关闭柜子时
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	@Transactional
	public void checkEveryShutDownInspectOut(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			if(null != out && !out.isEmpty()) {
				List<ToolModel> tools = new ArrayList<ToolModel>();
				@SuppressWarnings("unchecked")
				DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
				out.stream().forEach(toolCode->{
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						tool.setUseRecordStatus(1);
						toolMapper.updateById(tool);
						tools.add(tool);
						@SuppressWarnings("unchecked")
						ToolInspectDetail detail = inspectDetailMapper.selectOne(new Condition<ToolInspectDetail>().
								eq("master_id", masterId).eq("tool_id", tool.getId()));
						if(null == detail) {
							detail = new ToolInspectDetail();
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setExpiredTime(tool.getExpiredDate());
							detail.setHasInWarehouse(0);
							detail.setMasterId(masterId);
							detail.setOutWarehouseTime(new Date());
							detail.setToolId(tool.getId());
							inspectDetailMapper.insert(detail);
						}
					}else {
						log.error("工器具编号："+toolCode+"未入库，操作-检验出库-出");
					}
				});
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
			}
			
			if(null != in && !in.isEmpty()) {
				@SuppressWarnings("unchecked")
				List<ToolInspectDetail> result = inspectDetailMapper.selectList(new Condition<ToolInspectDetail>().eq("master_id", masterId));
				List<String> needDeleteCodes = new ArrayList<String>();
				for(ToolInspectDetail vo : result) {
					ToolModel tool = toolMapper.selectById(vo.getToolId());
					for(String toolCode : in) {
						if(tool.getCode().equals(toolCode)) {
							needDeleteCodes.add(toolCode);
							break;
						}
					}
				}
				//有值说明可能是从一个柜子转移到另一个柜子
				//那么删除这些工器具的借据明显
				if(!needDeleteCodes.isEmpty()) {
					inspectDetailMapper.deleteInspectDetailByToolCodesAndMasterId(needDeleteCodes,masterId);
				}
				
				//如果还有工器具不在借据之内，可能就是之前借的，那么生成一个还的记录
				if(in.size() > needDeleteCodes.size()) {
					in.removeAll(needDeleteCodes);
					ToolReturnMaster master = new ToolReturnMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolReturnMasterMapper.insert(master);
					@SuppressWarnings("unchecked")
					DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
					List<ToolModel> tools = new ArrayList<ToolModel>();
					for(String toolCode : in) {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							tool.setUseRecordStatus(2);
							tool.setDeviceId(device.getId());
							toolMapper.updateById(tool);
							tools.add(tool);
							ToolReturnDetail detail = new ToolReturnDetail();
							detail.setMasterId(master.getId());
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setToolId(tool.getId());
							toolReturnDetailMapper.insert(detail);
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-检验出库-入");
						}
					}
					//发送消息到主站
					//commonSendInfo.sendToolInfoToMaster(tools);
					toolBorrowMapper.updateToolBorrowHasReturn(master.getId(),
							(String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null),
							device.getId());
				}
			}
		}
	}
	
	/**
	 * 
	 * @description  检验归还时
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	@Transactional
	public void checkEveryShutDownInspectIn(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			List<String> needDeleteCodes = new ArrayList<String>();
			@SuppressWarnings("unchecked")
			DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
			if(null != in && !in.isEmpty()) {
				List<ToolModel> tools = new ArrayList<ToolModel>();
				for(String toolCode : in) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						tool.setUseRecordStatus(1);
						tool.setDeviceId(device.getId());
						toolMapper.updateById(tool);
						tools.add(tool);
						@SuppressWarnings("unchecked")
						ToolInspectInDetail detail = inspectInDetailMapper.selectOne(new Condition<ToolInspectInDetail>().
								eq("master_id", masterId).eq("tool_id", tool.getId()));
						if(null == detail) {
							detail = new ToolInspectInDetail();
							detail.setDeviceId(device.getId());
							detail.setMasterId(masterId);
							detail.setToolId(tool.getId());
							inspectInDetailMapper.insert(detail);
						}
					}else {
						log.error("工器具编号："+toolCode+"未入库，操作-检验入库-入");
					}
				}
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
			}
			@SuppressWarnings("unchecked")
			List<ToolInspectInDetail> result = inspectInDetailMapper.selectList(new Condition<ToolInspectInDetail>().eq("master_id", masterId));
			if(null != out && !out.isEmpty()) {
				for(String toolCode : out) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						ToolInspectInDetail find = null;
						for(ToolInspectInDetail vo : result) {
							if(vo.getToolId().equals(tool.getId())) {
								needDeleteCodes.add(toolCode);
								find = vo;
								break;
							}
						}
						if(null != find) {
							inspectInDetailMapper.deleteById(find.getId());
						}
					}else {
						log.error("工器具编号："+toolCode+"未入库，操作-检验入库-出");
					}
				}
				
				//如果还有工器具不在还据之内，那么生成一个借的记录
				if(out.size() > needDeleteCodes.size()) {
					out.removeAll(needDeleteCodes);
					ToolBorrowMaster master = new ToolBorrowMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolBorrowMasterMapper.insert(master);
					List<ToolModel> tools = new ArrayList<ToolModel>();
					for(String toolCode : out) {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							tool.setUseRecordStatus(1);
							toolMapper.updateById(tool);
							tools.add(tool);
							ToolBorrowDetail detail = new ToolBorrowDetail();
							detail.setMasterId(masterId);
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setExpiredTime(tool.getExpiredDate());
							detail.setHasReturn(0);
							detail.setToolId(tool.getId());
							toolBorrowDetailMapper.insert(detail);
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-检验入库-出");
						}
					}
					//发送消息到主站
					//commonSendInfo.sendToolInfoToMaster(tools);
				}
			}
		}
	}
	
	/**
	 * 
	 * @description  检查中每次关柜子时检查 1:借，2：还
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月18日
	 * @return void
	 */
	@Transactional
	public void checkEveryShutDownInCheck(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			String userId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null);
			if(null != out && !out.isEmpty()) {
				String masterId = toolBorrowMapper.selectUserLastBorrowMasterId(userId);
				if(null == masterId) {
					ToolBorrowMaster master = new ToolBorrowMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolBorrowMasterMapper.insert(master);
					masterId = master.getId();
				}
				
				@SuppressWarnings("unchecked")
				DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
				List<ToolModel> tools = new ArrayList<ToolModel>();
				for(String toolCode : out) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						tool.setUseRecordStatus(0);
						toolMapper.updateById(tool);
						tools.add(tool);
						ToolBorrowDetail detail = new ToolBorrowDetail();
						detail.setMasterId(masterId);
						detail.setCreateTime(new Date());
						detail.setCreateUser(WebUtils.username());
						detail.setDeviceId(device.getId());
						detail.setExpiredTime(tool.getExpiredDate());
						detail.setHasReturn(0);
						detail.setToolId(tool.getId());
						toolBorrowDetailMapper.insert(detail);
					}else {
						log.error("工器具编号："+toolCode+"未入库，操作-检查-出");
					}
				}
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
			}
			
			if(null != in && !in.isEmpty()) {
				String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
				if(null == masterId) {
					ToolReturnMaster master = new ToolReturnMaster();
					master.setCreateTime(new Date());
					master.setUserId(userId);
					master.setStatus(0);
					toolReturnMasterMapper.insert(master);
					masterId = master.getId();
					CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), masterId);
					CacheOperatorInfo.setMapValue(CacheKeyName.BUSINESS_OPERATE_TYPE.getValue(), OperateType.CHECK_WAREHOUSE.getValue());
				}
				@SuppressWarnings("unchecked")
				DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
				List<ToolModel> tools = new ArrayList<ToolModel>();
				for(String toolCode : in) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						tool.setUseRecordStatus(2);
						tool.setDeviceId(device.getId());
						toolMapper.updateById(tool);
						tools.add(tool);
						ToolReturnDetail detail = new ToolReturnDetail();
						detail.setMasterId(masterId);
						detail.setCreateTime(new Date());
						detail.setCreateUser(WebUtils.username());
						detail.setDeviceId(device.getId());
						detail.setToolId(tool.getId());
						toolReturnDetailMapper.insert(detail);
					}else {
						log.error("工器具编号："+toolCode+"未入库，操作-检查-入");
					}
				}
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
				toolBorrowMapper.updateToolBorrowHasReturn(masterId,
						(String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null),
						device.getId());
			}
		}
	}
	/**
	 * 
	 * @description 新增入库
	 * @param exist
	 * @param in
	 * @param out
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月31日
	 * @return void
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public void checkEveryShutDownAddNewTool(List<String> exist,List<String> in,List<String> out,String deviceCode) {
		synchronized(this) {
			DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().eq("code", deviceCode));
			String masterId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			if(null != in && !in.isEmpty()) {
				List<String> addCodes = (List<String>)CacheOperatorInfo.getMapValue(
						CacheKeyName.TOOL_WAIT_OPERATE_CODES.getValue(), new ArrayList<String>());
				
				for(String inCode : in) {
					if(!addCodes.contains(inCode)) {
						addCodes.add(inCode);
						ToolInWarehouseRecord record = toolInWarehouseRecordMapper.selectOne(
								new Condition<ToolInWarehouseRecord>().eq("tool_code", inCode).eq("master_id", masterId));
						if(null != record) {
							record.setStatus(0);
							record.setDeviceId(device.getId());
							toolInWarehouseRecordMapper.updateById(record);
						}
					}
				}
				CacheOperatorInfo.setMapValue(CacheKeyName.TOOL_WAIT_OPERATE_CODES.getValue(), addCodes);
			}
			
			if(null != out && !out.isEmpty()) {
				//判断是不是还未入的工器具
				List<String> existCodes = (List<String>)CacheOperatorInfo.getMapValue(
						CacheKeyName.TOOL_WAIT_OPERATE_CODES.getValue(), new ArrayList<String>());
				List<String> needDelete = new ArrayList<String>();
				out.stream().forEach(o->{
					if(existCodes.contains(o)) {
						needDelete.add(o);
						ToolInWarehouseRecord record = toolInWarehouseRecordMapper.selectOne(
								new Condition<ToolInWarehouseRecord>().eq("tool_code", o).eq("master_id", masterId));
						if(null != record) {
							record.setStatus(-1);
							toolInWarehouseRecordMapper.updateById(record);
						}
					}
				});
				
				if(!needDelete.isEmpty()) {
					existCodes.removeAll(needDelete);
				}
				
				//如果有出的记录，那么生成一个借的记录
				if(out.size() > 0) {
					ToolBorrowMaster master = new ToolBorrowMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null));
					master.setStatus(0);
					toolBorrowMasterMapper.insert(master);
					List<ToolModel> tools = new ArrayList<ToolModel>();
					for(String toolCode : out) {
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
						if(null != tool) {
							tool.setUseRecordStatus(2);
							toolMapper.updateById(tool);
							tools.add(tool);
							ToolBorrowDetail detail = new ToolBorrowDetail();
							detail.setMasterId(masterId);
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setExpiredTime(tool.getExpiredDate());
							detail.setHasReturn(0);
							detail.setToolId(tool.getId());
							toolBorrowDetailMapper.insert(detail);
						}else {
							log.error("工器具编号："+toolCode+"未入库，操作-新增入库-出");
						}
					}
					//发送消息到主站
					//commonSendInfo.sendToolInfoToMaster(tools);
					toolBorrowMapper.updateToolBorrowHasReturn(master.getId(),
							(String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null),
							device.getId());
				}
			}
		}
	}
	
	/**
	 * 记录当前柜子里面的所有工器具
	 */
	@Transactional
	public void produceAllToolRecordByDeviceClosed(DeviceWarehouseDTO deviceWarehouse) {
		synchronized(this) {
			ToolWarehouseMaster masterDb = new ToolWarehouseMaster();
			masterDb.setCreateTime(new Date());
			masterDb.setDeviceCode(deviceWarehouse.getDeviceCode());
			masterDb.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(),null));
			//toolWarehouseMasterMapper.insert(masterDb);
			if(null != deviceWarehouse && null !=deviceWarehouse.getToolCodes() && 
					!deviceWarehouse.getToolCodes().isEmpty()) {
				deviceWarehouse.getToolCodes().stream().forEach(detail->{
					ToolWarehouseDetail detailDb = new ToolWarehouseDetail();
					detailDb.setMasterId(masterDb.getId());
					detailDb.setToolCode(detail);
					//toolWarehouseDetailMapper.insert(detailDb);
				});
			}
			//出库
			if(null != deviceWarehouse && null !=deviceWarehouse.getDownCodes() && 
					!deviceWarehouse.getDownCodes().isEmpty()) {
				List<String> outRfIds = deviceWarehouse.getDownCodes().stream().collect(Collectors.toList());
				//虽然是出库，但是检查一下是否还在柜子中
				List<String> noOutCodes = commonMapper.selectNoOutTools(deviceWarehouse.getDeviceCode(),outRfIds);
				if(null != noOutCodes && !noOutCodes.isEmpty()) {
					outRfIds.removeAll(noOutCodes);
				}
				if(null != outRfIds && !outRfIds.isEmpty()) {
					commonMapper.updateToolOutDevice(outRfIds);
				}
				//commonSendInfo.sendToolInfoByRfIds(outRfIds, 2, deviceWarehouse.getDeviceCode());
			}
			//入库
			if(null != deviceWarehouse && null !=deviceWarehouse.getUpCodes() && 
					!deviceWarehouse.getUpCodes().isEmpty()) {
				//List<String> inRfIds = deviceWarehouse.getUpCodes().stream().collect(Collectors.toList());
				//commonSendInfo.sendToolInfoByRfIds(inRfIds, 1, deviceWarehouse.getDeviceCode());
			}
			//更新工器具所在柜子
			if(null != deviceWarehouse.getToolCodes() && deviceWarehouse.getToolCodes().size() > 0) {
				commonMapper.updateToolInDevice(deviceWarehouse.getDeviceCode(), 
						deviceWarehouse.getToolCodes());
				List<String> notInDeviceRfIds = commonMapper.checkToolNoDesctDevice(deviceWarehouse.getDeviceCode(),
						deviceWarehouse.getToolCodes());
				if(null != notInDeviceRfIds && !notInDeviceRfIds.isEmpty()) {
					commonMapper.updateToolOutDevice(notInDeviceRfIds);
					//commonSendInfo.sendToolInfoByRfIds(notInDeviceRfIds, 1, deviceWarehouse.getDeviceCode());
				}
			}
		}
	}
	
	public void deviceRunning(List<DeviceRunningStateSchema> stats) {
		if(null != stats && !stats.isEmpty()) {
			List<DeviceModel> needUpdates = new ArrayList<DeviceModel>();
			stats.stream().forEach(stat->{
				@SuppressWarnings("unchecked")
				DeviceModel device = deviceMapper.selectOne(new Condition<ToolModel>().eq("code", stat.getCode()));
				if(null != device) {
					device.setDeviceState(stat.getDeviceStat());
					device.setTemperature(stat.getTemperature());
					device.setTemperatureStat(stat.getTemperatureStat());
					deviceMapper.updateById(device);
					needUpdates.add(device);
					ToolRunning running = new ToolRunning();
					BeanUtils.copyProperties(stat, running);
					running.setDeviceId(device.getId());
					running.setCreateTime(new Date());
					deviceRunningMapper.insert(running);
				}
			});
			//commonSendInfo.sendDeviceInfoToMaster(needUpdates);
		}
	}
	
	/**
	 * 
	 * @description 解析消息
	 * @param info
	 * @auther 韩兵
	 * @Date 2020年7月28日
	 * @return void
	 */
	@SuppressWarnings("unchecked")
	public void receiveDeviceInfo(BoxDeviceInfoDTO info) {
		if(!StringUtils.isBlank(info.getTopic())) {
			//所有柜子编号
			List<String> allDeviceCode = deviceService.getAllDeviceCode(null);
			String topicCode = info.getTopic().split("/")[1];
			String commanType = info.getTopic().split("/")[0];
			if(allDeviceCode.contains(topicCode)) {
				try {
					log.info("收到柜子数据："+JsonUtils.toJsonString(info));
				} catch (IOException e) {
					log.error("接受柜子数据异常",e);
				}
				Map<String,Object> body = null;
				try {
					body = JsonUtils.readFromJson(info.getPayload().replaceAll("&quot;", "\""), HashMap.class);
				} catch (IOException e) {
					log.error("解析柜子消息异常", e);
				}
				//库存
				List<String> existCodes = null;
				//入库
				List<String> upCodes = null;
				//出库
				List<String> downCodes = null;
				if(null != body && !body.isEmpty()) {
					Integer code = (Integer)body.get("code");
					Integer errCode = (Integer)body.get("err_code");
					Map<String,Object> data = null;
//					String tradeNo = "";
//					String sendTradeNo = (String)CacheOperatorInfo.getMapValue(
//							CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), null);
					if(null == errCode) {
						try {
							deviceResetTimes.remove(topicCode);
						}catch(Exception e) {
							log.error("delete device reset comand cahce map exception:{}",e);
						}
						//心跳
						if(COMMAND_HEARTBEAT.equals(commanType)) {
							Integer lock = Integer.parseInt(null==body.get("lock")?"-1":body.get("lock").toString());
							Integer door = Integer.parseInt(null==body.get("door")?"-1":body.get("door").toString());
							BigDecimal humidity = new BigDecimal(null==body.get("humidity")?"-1":body.get("humidity").toString());
							BigDecimal temperature = new BigDecimal(null==body.get("temperature")?"-1":body.get("temperature").toString());
							handlerDeviceHeartBeat(topicCode,lock,door,temperature,humidity);
						//反馈
						}else if(COMMAND_FEEDBACK.equals(commanType)){
							//tradeNo = (String)body.get("trade_no");
							data = (Map<String,Object>)body.get("data");
							if(code.equals(MqttSendCommandFunc.COMMAND_3015.getValue())) {
								existCodes = (List<String>)data.get("scan_epcs");
								upCodes = (List<String>)data.get("up_epcs");
								downCodes = (List<String>)data.get("down_epcs");
							}
							
							Integer lock = Integer.parseInt(null==data.get("lock")?"-1":data.get("lock").toString());
							Integer door = Integer.parseInt(null==data.get("door")?"-1":data.get("door").toString());
							BigDecimal temperature = null==data.get("temperature")?null:new BigDecimal(data.get("temperature").toString());
							BigDecimal humidity = null==data.get("humidity")?null:new BigDecimal(data.get("humidity").toString());
							log.info("---------------------------------收到反馈命令:"+code+",柜子编号："+topicCode);
							switch(code) {
								case 3000:
									break;
								case 3001:
									handlerDeviceHeartBeat(topicCode,lock,door,temperature,humidity);
									break;
								case 3002:
									handlerDeviceHeartBeat(topicCode,lock,door,temperature,humidity);
									break;
								case 3010:
									handlerDeviceInfo(topicCode,lock,door);
									break;
								case 3011://开锁的状态
									handlerDeviceInfo(topicCode,lock,door);
									break;
								case 3015:
									//if(!StringUtils.isBlank(sendTradeNo) && sendTradeNo.equals(tradeNo)) {
										DeviceWarehouseDTO param = new DeviceWarehouseDTO();
										param.setDeviceCode(topicCode);
										param.setToolCodes(existCodes);
										param.setUpCodes(upCodes);
										param.setDownCodes(downCodes);
										receiveDeviceDatas(param);
									//}
									break;
								case 3016:
									handlerDeviceInfo(topicCode,lock,door);
									break;
								case 3060:
									handlerDeviceHeartBeat(topicCode,lock,door,temperature,humidity);
									handlerDeviceInfo(topicCode,lock,door);
									break;
								default:
							}
						}
					}else if(errCode.equals(MqttSendCommandFunc.COMMAND_1011.getValue())){
						log.info("----------------------柜子上个任务未完成，发送重置命令，柜子编号："+topicCode);
						try {
							log.info("收到柜子数据："+JsonUtils.toJsonString(info));
						} catch (IOException e) {
							log.error("解析柜子数据异常",e);
						}
						//if(!StringUtils.isBlank(sendTradeNo) && sendTradeNo.equals(tradeNo)) {
							this.sendResetCommand(topicCode);
							this.sendCommandToSigleDevice(topicCode);
						//}
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @description  根据心跳更新设备状态
	 * @param deviceCode
	 * @param lock
	 * @param temperature
	 * @param humidity
	 * @auther 韩兵
	 * @Date 2020年7月28日
	 * @return void
	 */
	private void handlerDeviceHeartBeat(String deviceCode,Integer lock,Integer door,
			BigDecimal temperature,BigDecimal humidity) {
		List<DeviceModel> needUpdates = new ArrayList<DeviceModel>();
		@SuppressWarnings("unchecked")
		DeviceModel device = deviceMapper.selectOne(new Condition<>().eq("code", deviceCode));
		BigDecimal maxHumidity = appConfig.getDeviceMaxHumidity();
		BigDecimal maxTemperature = appConfig.getDeviceMaxTemperature();
		BigDecimal minHumidity = appConfig.getDeviceMinHumidity();
		BigDecimal minTemperature = appConfig.getDeviceMinTemperature();
		
		Integer humidityStat = 1;
		Integer temperatureStat = 1;
		if(null == temperature) {
			temperatureStat = null;
		}
		if(null != temperature && temperature.compareTo(maxTemperature) <= 0 && temperature.compareTo(minTemperature) >= 0) {
			temperatureStat = 0;
		}
		if(null == humidity) {
			humidityStat = null;
		}
		if(null != humidity && humidity.compareTo(maxHumidity) <= 0 && humidity.compareTo(minHumidity) >= 0) {
			humidityStat = 0;
		}
		
		DeviceStateModel deviceStat = new DeviceStateModel();
		deviceStat.setCreateTime(new Date());
		deviceStat.setDeviceId(device.getId());
		deviceStat.setDeviceState(door==1?-1:lock==1?0:1);
		deviceStat.setHumidity(humidity);
		deviceStat.setHumidityStat(humidityStat);
		deviceStat.setTemperature(temperature);
		deviceStat.setTemperatureStat(temperatureStat);
		deviceStateMapper.insert(deviceStat);
		
		device.setDeviceState(lock==1?0:1);
		device.setTemperature(temperature);
		device.setTemperatureStat(temperatureStat);
		deviceMapper.updateById(device);
		
		needUpdates.add(device);
		//commonSendInfo.sendDeviceInfoToMaster(needUpdates);
	}
	
	/**
	 * 
	 * @description 检查是否已处理完成
	 * @param deviceCode
	 * @param lock
	 * @auther 韩兵
	 * @Date 2020年7月28日
	 * @return void
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void handlerDeviceInfo(String deviceCode,Integer lock,Integer door) {
		try {
			log.info("--------------------------柜子状态返回");
			//更新柜子状态
			DeviceModel device = deviceMapper.selectOne(new Condition<>().eq("code", deviceCode));
			device.setDeviceState(door==1?-1:lock==1?0:1);
			deviceMapper.updateById(device);
			List<String> deviceCodes = (List)CacheOperatorInfo.getMapValue(
					CacheKeyName.NEED_CHECK_DOOR_DEVICE_LIST.getValue(), null);
			log.info("--------------------------需要检查的工器具编号："+deviceCodes!=null&&!deviceCodes.isEmpty()?deviceCodes.toString():"");
			if(null != deviceCodes && !deviceCodes.isEmpty()) {
				log.info("--------------------------1已关门工器具柜编号："+deviceCode);
				if(deviceCodes.contains(deviceCode) && door == 0) {
					log.info("--------------------------2已关门工器具柜编号："+deviceCode);
					deviceCodes.remove(deviceCode);
				}
			}
		}catch(Exception e) {
			log.error("检查柜门是否关闭异常{}"+e);
		}
	}
	
	/**
	 * 
	 * @description 发送消息到柜子
	 * @param commandCode 2000:开门；2002：关门；（关门时要检查反馈是否关闭）
	 * @return
	 * @auther 韩兵
	 * @Date 2020年7月28日
	 * @return ApiResult
	 */
	@SuppressWarnings("rawtypes")
	public ApiResult sendCommandToDevice(Integer commandCode) {
		//保存发送的命令
		CacheOperatorInfo.setMapValue(CacheKeyName.DEVICE_WAIT_OPERATE_CODE.getValue(), commandCode);
		log.info("统一发送命令--------------------------------------------下发指令："+commandCode);
		List<String> allDeviceCode = deviceService.getAllDeviceCode(-2);
		CacheOperatorInfo.setMapValue(CacheKeyName.NEED_CHECK_DOOR_DEVICE_LIST.getValue(), allDeviceCode);
		
		for (int i = 0; i < allDeviceCode.size(); i++) {
			ExternalJsonObjectDTO dto = new ExternalJsonObjectDTO();
			dto.setCommand(commandCode);
			dto.setTrade_no(System.currentTimeMillis()+"");
			BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
			req.setTopic("command/"+allDeviceCode.get(i));
			try {
				req.setPayload(JsonUtils.toJsonString(dto));
			} catch (IOException e) {
				log.error("下发柜子命令json报错", e);
			}
			try {
				log.info("下发柜子命令："+JsonUtils.toJsonString(req));
			} catch (IOException e) {
				log.error("下发柜子命令json报错", e);
			}
			try {
				//缓存交易号
				CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
						dto.getTrade_no());
				restBiz.postForEntity(
						appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
			} catch(Exception e) {
				log.error("下发命令",e);
			}
		}
		
		return ApiResult.success();
	}
	
	/**
	 * 
	 * @description 发送重置工器具命令
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年8月19日
	 * @return void
	 */
	public void sendResetCommand(String deviceCode) {
		ExternalJsonObjectDTO dto = new ExternalJsonObjectDTO();
		dto.setCommand(MqttSendCommandFunc.COMMAND_2062.getValue());
		dto.setTrade_no(System.currentTimeMillis()+"");
		BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
		req.setTopic("command/"+deviceCode);
		try {
			req.setPayload(JsonUtils.toJsonString(dto));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			log.info("下发柜子命令："+JsonUtils.toJsonString(req));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		//设置失败的次数
		Integer times = deviceResetTimes.get(deviceCode);
		deviceResetTimes.put(deviceCode, null == times?1:times+1);
		if(null == times || times <= 3) {
			log.info("发送重置命令--------------------------------------------下发指令，device：："+deviceCode);
			try {
				//缓存交易号
				CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
						dto.getTrade_no());
				restBiz.postForEntity(
						appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
			} catch(Exception e) {
				log.error("下发命令",e);
			}
		}
	}
	
	/**
	 * 
	 * @description 单个发送命令
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年8月19日
	 * @return void
	 */
	public void sendCommandToSigleDevice(String deviceCode) {
		Integer commandCode = (Integer)CacheOperatorInfo.getMapValue(CacheKeyName.DEVICE_WAIT_OPERATE_CODE.getValue(), null);
		log.info("单个--------------------------------------------下发指令："+commandCode);
		ExternalJsonObjectDTO dto = new ExternalJsonObjectDTO();
		dto.setCommand(commandCode);
		dto.setTrade_no(System.currentTimeMillis()+"");
		BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
		req.setTopic("command/"+deviceCode);
		try {
			req.setPayload(JsonUtils.toJsonString(dto));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			log.info("下发柜子命令："+JsonUtils.toJsonString(req));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			//缓存交易号
			CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
					dto.getTrade_no());
			restBiz.postForEntity(
					appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
	}
	
	/**
	 * 
	 * @description 检查柜门的锁状态
	 * @auther 韩兵
	 * @Date 2020年7月28日
	 * @return void
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public ApiResult confirmDeviceDoor() {
		log.info("---------------------------检查柜子是否已关门开始");
		//检查所有柜子是否关闭-发送命令
		ApiResult check = this.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2060.getValue());
		if(!check.isSuccess()) {
			return check;
		}
		Boolean checkResult = false;
		Calendar c = Calendar.getInstance();
		c.add(Calendar.SECOND, appConfig.getWaitSeconds());
		Boolean hasExpired = false;
		List<String> deviceCodes = null;
		while(!hasExpired && !checkResult) {
			//检查柜门的关闭情况
			deviceCodes = (List)CacheOperatorInfo.getMapValue(
					CacheKeyName.NEED_CHECK_DOOR_DEVICE_LIST.getValue(), null);
			if(null == deviceCodes || deviceCodes.isEmpty()) {
				checkResult = true;
			}
			Date now = new Date();
			if(now.compareTo(c.getTime()) > 0) {
				hasExpired = true;
			}
		}
		log.info("---------------------------检查的结果："+checkResult);
		if(!checkResult) {
			//查询数据库状态是否已经关闭
			List<String> unLockCodes = deviceMapper.selectUnlockDevice(deviceCodes);
			if(null != unLockCodes && !unLockCodes.isEmpty()) {
				log.info("database check result:查询codes("+ deviceCodes +"),未关闭codes("+ unLockCodes +")");
				return ApiResult.fail(unLockCodes +"柜门未关闭");
			}
		}
		
		return ApiResult.success();
	}
	
	/**
	 * 
	 * @description 设置指示灯
	 * @param codes  柜子编号
	 * @param status 0-关 1-开
	 * @auther 韩兵
	 * @Date 2020年8月21日
	 * @return void
	 */
	public void sendLightCommand(List<String> codes,Integer status) {
		if(null != codes && !codes.isEmpty()) {
			codes.stream().forEach(code->{
				DeviceLightCommandDTO dto = new DeviceLightCommandDTO();
				dto.setCommand(MqttSendCommandFunc.COMMAND_2200.getValue());
				dto.setTrade_no(System.currentTimeMillis()+"");
				dto.setNumber(appConfig.getDeviceLightNum());
				dto.setStatus(status);
				BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
				req.setTopic("command/"+code);
				try {
					req.setPayload(JsonUtils.toJsonString(dto));
				} catch (IOException e) {
					log.error("下发柜子命令json报错", e);
				}
				try {
					//缓存交易号
					CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
							dto.getTrade_no());
					restBiz.postForEntity(
							appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
				} catch(Exception e) {
					log.error("下发命令",e);
				}
			});
		}
	}
	
	/**
	 * 
	 * @description 上锁
	 * @auther 韩兵
	 * @Date 2020年7月31日
	 * @return void
	 */
	public void lockDevice() {
		//柜门上电子锁-发送命令
		this.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2002.getValue());
	}
	
	/**
	 * 
	 * @description 开启读写器的扫描
	 * @auther 韩兵
	 * @Date 2020年7月30日
	 * @return void
	 */
	public void sendIvgScanStartCommand() {
		log.info("----------------------------开启读写器命令："+appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgScan());
		ResponseEntity<?> entity = restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgScan(),
				String.class);
		if(null != entity && entity.getStatusCode() == HttpStatus.OK) {
			String result = (String)entity.getBody();
			if(!"OK".equals(result)) {
				try {
					restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgScan(),
							String.class);
				} catch(Exception e) {
					log.error("下发命令",e);
				}
			}
		}
		
	}
	
	/**
	 * 
	 * @description 停止读写器的扫描
	 * @auther 韩兵
	 * @Date 2020年8月7日
	 * @return void
	 */
	public void sendIvgScanStopCommand() {
		log.info("----------------------------停止读写器命令："+appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgStopScan());
		ResponseEntity<?> entity = null;
		try {
			entity = restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgStopScan(),
					String.class);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
		
		if(null != entity && entity.getStatusCode() == HttpStatus.OK) {
			String result = (String)entity.getBody();
			if(!"OK".equals(result)) {
				try {
					restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getSendCommandIvgStopScan(),
							String.class);
				} catch(Exception e) {
					log.error("下发命令",e);
				}
			}
		}
	}
	
	/**
	 * 
	 * @description 设置工器具编号
	 * @param tid
	 * @param epc
	 * @auther 韩兵
	 * @Date 2020年7月30日
	 * @return void
	 */
	public Boolean sendSetCodeCommand(String tid,String epc) {
		Map<String,String> param = new HashMap<String,String>();
		param.put("tid", tid);
		param.put("epc", epc);
		ResponseEntity<?> entity = null;
		try {
			entity = restBiz.postForEntityOhter(appConfig.getCommunicationApiUrl()+
					appConfig.getSendCommandIvgSet(),
					param,Object.class,param);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
		if(null != entity && entity.getStatusCode() == HttpStatus.OK) {
			return (Boolean)entity.getBody();
		}
		return false;
	}
	
	/**
	 * 
	 * @description  处理远程返回的工器具编号
	 * @param tid
	 * @param epc
	 * @auther 韩兵
	 * @Date 2020年7月31日
	 * @return void
	 */
	public void getToolFromRemote(List<String> tid,List<String> epc) {
		String readLog = (String) CacheOperatorInfo.getMapValue(
				CacheKeyName.READER_LOG.getValue(), CacheKeyName.READER_LOG.getValue());
		if("1".equals(readLog)){
			// 报废读取
			//循环加入报废清单
			if(null != epc && !epc.isEmpty()) {
				for(String epc1 : epc) {
					try {
						@SuppressWarnings("unchecked")
						ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", epc1));
						if(null != tool) {
							webSocketUtil.sendMsgForScrapDetail(tool.getId());
						}else {
							log.error("加入报废清单，工器具编号："+epc1+"未查询到");
						}
					}catch(Exception e) {
						log.error("扫描加入报废清单异常：",e);
					}
				}
			}
		}else if("2".equals(readLog)){
			// 入库读取
			String readerCodeList = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.READER_CODE_LIST.getValue(), CacheKeyName.READER_CODE_LIST.getValue());
			String tidExist = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.TID_VALUE.getValue(), CacheKeyName.TID_VALUE.getValue());
			if(!CacheKeyName.READER_CODE_LIST.getValue().equals(readerCodeList)&&
					!CacheKeyName.TID_VALUE.getValue().equals(tidExist)) {
				for(String one : epc) {
					if(!readerCodeList.contains(one)) {
						String[] readerCodeListArray = readerCodeList.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						readerCodeList = StringUtils.join(arrays,",");
					}
				}
				for(String one : tid) {
					if(!tidExist.contains(one)) {
						String[] readerCodeListArray = tidExist.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						tidExist = StringUtils.join(arrays,",");
					}
				}
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), tidExist);
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), readerCodeList);
			}else {
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), StringUtils.join(tid, ","));
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), StringUtils.join(epc, ","));
			}
		}else if("3".equals(readLog)){
			//修改读取
			String readerCodeList = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.READER_CODE_LIST.getValue(), CacheKeyName.READER_CODE_LIST.getValue());
			String tidExist = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.TID_VALUE.getValue(), CacheKeyName.TID_VALUE.getValue());
			if(!CacheKeyName.READER_CODE_LIST.getValue().equals(readerCodeList)&&
					!CacheKeyName.TID_VALUE.getValue().equals(tidExist)) {
				for(String one : epc) {
					if(!readerCodeList.contains(one)) {
						String[] readerCodeListArray = readerCodeList.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						readerCodeList = StringUtils.join(arrays,",");
					}
				}
				for(String one : tid) {
					if(!tidExist.contains(one)) {
						String[] readerCodeListArray = tidExist.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						tidExist = StringUtils.join(arrays,",");
					}
				}
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), tidExist);
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), readerCodeList);
			}else {
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), StringUtils.join(tid, ","));
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), StringUtils.join(epc, ","));
			}
		}else if("4".equals(readLog)){
			//修改读取
			String readerCodeList = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.READER_CODE_LIST.getValue(), CacheKeyName.READER_CODE_LIST.getValue());
			String tidExist = (String) CacheOperatorInfo.getMapValue(
					CacheKeyName.TID_VALUE.getValue(), CacheKeyName.TID_VALUE.getValue());
			if(!CacheKeyName.READER_CODE_LIST.getValue().equals(readerCodeList)&&
					!CacheKeyName.TID_VALUE.getValue().equals(tidExist)) {
				for(String one : epc) {
					if(!readerCodeList.contains(one)) {
						String[] readerCodeListArray = readerCodeList.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						readerCodeList = StringUtils.join(arrays,",");
					}
				}
				for(String one : tid) {
					if(!tidExist.contains(one)) {
						String[] readerCodeListArray = tidExist.split(",");
						List<String> arrays = new ArrayList<String>(Arrays.asList(readerCodeListArray));
						arrays.add(one);
						tidExist = StringUtils.join(arrays,",");
					}
				}
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), tidExist);
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), readerCodeList);
			}else {
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), StringUtils.join(tid, ","));
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), StringUtils.join(epc, ","));
			}
		}
	}
	
	
	
	/**
	 * 
	 * @description  生成借与归还记录
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月17日
	 * @return void
	 */
	@Transactional
	public void produceInOutSignleDeviceWarehouseRecord(String deviceCode,
			List<String> out,List<String> in) {
		synchronized(this) {
			@SuppressWarnings("unchecked")
			DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().
					eq("code", deviceCode));
			String masterId = (String)CacheOperatorInfo.getMapValue(
					CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
			//出库
			if(null != out && !out.isEmpty()) {	
				if(masterId == null) {
					ToolBorrowMaster master = new ToolBorrowMaster();
					master.setCreateUser(WebUtils.username());
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), 
							null));
					master.setStatus(0);
					toolBorrowMasterMapper.insert(master);
					masterId = master.getId();
				}
				
				//库存所有工器具
				List<String> inDevices = toolMapper.queryAllCodesForDevice();
				List<ToolModel> tools = new ArrayList<ToolModel>();
				for(String toolCode : out) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						
						//虽然是出，判断是否是在柜子中
						if(!inDevices.contains(toolCode)) {
							tool.setUseRecordStatus(0);
							toolMapper.updateById(tool);
							tools.add(tool);
							@SuppressWarnings("unchecked")
							ToolBorrowDetail detail = toolBorrowDetailMapper.selectOne(new Condition<ToolBorrowDetail>().
									eq("master_id", masterId).eq("tool_id", tool.getId()));
							if(detail == null) {
								detail = new ToolBorrowDetail();
								detail.setMasterId(masterId);
								detail.setCreateTime(new Date());
								detail.setCreateUser(WebUtils.username());
								detail.setDeviceId(device.getId());
								detail.setExpiredTime(tool.getExpiredDate());
								detail.setHasReturn(0);
								detail.setToolId(tool.getId());
								toolBorrowDetailMapper.insert(detail);
							}
						}
					}
				}
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
			}
			
			//入库
			if(null != in && !in.isEmpty()) {
				if(masterId == null) {
					ToolReturnMaster master = new ToolReturnMaster();
					master.setCreateTime(new Date());
					master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), 
							null));
					master.setStatus(0);
					toolReturnMasterMapper.insert(master);
					masterId = master.getId();
				}
				
				List<String> toolCodes = in;
				List<ToolModel> tools = new ArrayList<ToolModel>();
				for(String toolCode : toolCodes) {
					@SuppressWarnings("unchecked")
					ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
					if(null != tool) {
						tool.setUseRecordStatus(2);
						tool.setDeviceId(device.getId());
						toolMapper.updateById(tool);
						tools.add(tool);
						@SuppressWarnings("unchecked")
						ToolReturnDetail  detail = toolReturnDetailMapper.selectOne(new Condition<ToolReturnDetail>().
								eq("master_id", masterId).eq("tool_id", tool.getId()));
						if(detail == null) {
							detail = new ToolReturnDetail();
							detail.setMasterId(masterId);
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setToolId(tool.getId());
							toolReturnDetailMapper.insert(detail);
						}
					}
				}
				//发送消息到主站
				//commonSendInfo.sendToolInfoToMaster(tools);
			}
		}
	}
	
	
	/**
	 * 
	 * @description  生成检验出库与入库记录
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年7月17日
	 * @return void
	 */
	@Transactional
	public void produceInOutSignleDeviceInspect(String deviceCode,
			List<String> out,List<String> in) {
		@SuppressWarnings("unchecked")
		DeviceModel device = deviceMapper.selectOne(new Condition<DeviceModel>().
				eq("code", deviceCode));
		String masterId = (String)CacheOperatorInfo.getMapValue(
				CacheKeyName.BUSINESS_MASTER_ID.getValue(), null);
		//检验出库
		if(null != out && !out.isEmpty()) {
			if(masterId == null) {
				ToolInspectMaster master = new ToolInspectMaster();
				master.setCreateTime(new Date());
				master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), 
						null));
				inspectMasterMapper.insert(master);
				masterId = master.getId();
			}
			
			//库存所有工器具
			List<String> inDevices = toolMapper.queryAllCodesForDevice();
			List<ToolModel> tools = new ArrayList<ToolModel>();
			for(String toolCode : out) {
				@SuppressWarnings("unchecked")
				ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
				if(null != tool) {
					//虽然是出，判断是否是在柜子中
					if(!inDevices.contains(toolCode)) {
						tool.setUseRecordStatus(1);
						toolMapper.updateById(tool);
						tools.add(tool);
						@SuppressWarnings("unchecked")
						ToolBorrowDetail detail = toolBorrowDetailMapper.selectOne(new Condition<ToolBorrowDetail>().
								eq("master_id", masterId).eq("tool_id", tool.getId()));
						if(detail == null) {
							detail = new ToolBorrowDetail();
							detail.setMasterId(masterId);
							detail.setCreateTime(new Date());
							detail.setCreateUser(WebUtils.username());
							detail.setDeviceId(device.getId());
							detail.setExpiredTime(tool.getExpiredDate());
							detail.setHasReturn(0);
							detail.setToolId(tool.getId());
							toolBorrowDetailMapper.insert(detail);
						}
					}
				}else {
					log.error("检验出库未查询到编号："+toolCode);
				}
			}
			//发送消息到主站
			//commonSendInfo.sendToolInfoToMaster(tools);
		}
		
		//入库
		if(null != in && !in.isEmpty()) {
			if(masterId == null) {
				ToolReturnMaster master = new ToolReturnMaster();
				master.setCreateTime(new Date());
				master.setUserId((String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), 
						null));
				master.setStatus(0);
				toolReturnMasterMapper.insert(master);
				masterId = master.getId();
			}
			
			List<String> toolCodes = in;
			List<ToolModel> tools = new ArrayList<ToolModel>();
			for(String toolCode : toolCodes) {
				@SuppressWarnings("unchecked")
				ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", toolCode));
				if(null != tool) {
					tool.setUseRecordStatus(2);
					tool.setDeviceId(device.getId());
					toolMapper.updateById(tool);
					tools.add(tool);
					@SuppressWarnings("unchecked")
					ToolReturnDetail  detail = toolReturnDetailMapper.selectOne(new Condition<ToolReturnDetail>().
							eq("master_id", masterId).eq("tool_id", tool.getId()));
					if(detail == null) {
						detail = new ToolReturnDetail();
						detail.setMasterId(masterId);
						detail.setCreateTime(new Date());
						detail.setCreateUser(WebUtils.username());
						detail.setDeviceId(device.getId());
						detail.setToolId(tool.getId());
						toolReturnDetailMapper.insert(detail);
					}
				}else {
					log.error("检查出库未查询到编号："+toolCode);
				}
			}
			//发送消息到主站
			//commonSendInfo.sendToolInfoToMaster(tools);
		}
	}
	
	/**
	 * 
	 * @description ic卡读取的开始
	 * @auther 韩兵
	 * @Date 2020年8月23日
	 * @return void
	 */
	public void sendIcCardStart() {
		try {
			restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getIcCardStart(),
					Object.class);
		} catch(Exception e) {
			log.error("ic卡读取的关闭",e);
		}
	}
	
	/**
	 * 
	 * @description ic卡读取的关闭
	 * @auther 韩兵
	 * @Date 2020年8月23日
	 * @return void
	 */
	public void sendIcCardEnd() {
		try {
			restBiz.getForEntity(appConfig.getCommunicationApiUrl()+appConfig.getIcCardEnd(),
				Object.class);
		} catch(Exception e) {
			log.error("ic卡读取的关闭",e);
		}
	}
	
	/**
	 * 
	 * @description 查询需要领取的工器具所在柜子
	 * @param modelIds
	 * @return
	 * @auther 韩兵
	 * @Date 2020年8月7日
	 * @return List<String>
	 */
	public List<String> checkToolInDevice(List<String> modelIds){
		List<String> result = new ArrayList<String>();
		List<DeviceToolTypeVO> deviceModelIds = toolInWarehouseMasterMapper.selectDeviceWarehouseToolType();
		if(null != modelIds && !modelIds.isEmpty()) {
			for(String modelId : modelIds) {
				for(DeviceToolTypeVO typeVO : deviceModelIds) {
					if(modelId.equals(typeVO.getModelId())) {
						if(!result.contains(typeVO.getDeviceCode())) {
							result.add(typeVO.getDeviceCode());
						}
					}
				}
			}
		}
		return result;
	}
	
	public List<DeviceToolTypeVO> checkToolInDeviceNew(Map<String,BigDecimal> needBorrowData){
		List<DeviceToolTypeVO> result = new ArrayList<DeviceToolTypeVO>();
		List<DeviceToolTypeVO> deviceModelIds = toolInWarehouseMasterMapper.selectDeviceWarehouseToolType();
		if(null != needBorrowData && !needBorrowData.isEmpty()) {
			for(Map.Entry<String,BigDecimal> entry : needBorrowData.entrySet()) {
				for(int i=0;i<entry.getValue().intValue();i++) {
					for(DeviceToolTypeVO typeVO : deviceModelIds) {
						String[] standardIds = entry.getKey().split(",");
						if(ArrayUtils.contains(standardIds, typeVO.getModelId())) {
							if(!result.contains(typeVO)) {
								result.add(typeVO);
								break;
							}
						}
					}
				}
			}
		}
		return result;
	}
	
	public Boolean checkToolHasExpired(Date expiredTime) {
		if(null == expiredTime) {
			return false;
		}
		return expiredTime.compareTo(new Date()) < 0;
	}
	
	/**
	 * 
	 * @description 回到首页时检查未完成的任务
	 * @auther 韩兵
	 * @Date 2020年8月13日
	 * @return void
	 */
	public void checkUndoneTask() {
		//icCard读取的关闭
		this.sendIcCardEnd();
		this.sendIvgScanStopCommand();
		//检查柜门是否已关门
		if(confirmDeviceDoor().isSuccess()) {
			lockDevice();
		}else {
			//如果柜门未关闭-下发重置命令
			this.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2062.getValue());
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				log.error("程序等待异常:{}",e);
				Thread.currentThread().interrupt();
			}
			lockDevice();
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				log.error("程序等待异常:{}",e);
				Thread.currentThread().interrupt();
			}
			//再检查一遍是否已关闭
			if(confirmDeviceDoor().isSuccess()) {
				lockDevice();
			}
		}
		//设置熄灭灯的柜子
		List<String> allDeviceCode = deviceService.getAllDeviceCode(null);
		this.sendLightCommand(allDeviceCode, 0);
		//新增入库
		try {
			handlerNoDoneNewAdd();
		}catch(Exception e) {
			log.error("自动处理新增入库异常：{}",e);
		}
		//领取
		try {
			handlerBorrowNoDone();
		}catch(Exception e) {
			log.error("自动处理领用异常：{}",e);
		}
		//还
		try {
			handlerReturnNoDone();
		}catch(Exception e) {
			log.error("自动处理领用归还异常：{}",e);
		}
		//检验出库
		try {
			handlerInspectOutNoDone();
		}catch(Exception e) {
			log.error("自动处理检验出库异常：{}",e);
		}
		//检验入库
		try {
			handlerInspectInNoDone();
		}catch(Exception e) {
			log.error("自动处理检验入库异常：{}",e);
		}
	}
	
	/**
	 * 
	 * @description  处理新增入库未完成的数据
	 * @auther 韩兵
	 * @Date 2020年8月14日
	 * @return void
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public void handlerNoDoneNewAdd() {
		//查询未处理的新增入库
		List<ToolInWarehouseMaster> masters = toolInWarehouseMasterMapper.selectList(
				new Condition<ToolInWarehouseMaster>().eq("status", 0));
		if(null != masters && !masters.isEmpty()) {
			masters.stream().forEach(master->{
				List<ToolInWarehouseRecord> newInRecords = toolInWarehouseRecordMapper.selectList(
						new Condition<ToolInWarehouseRecord>().eq("master_id", master.getId()).eq("status", 0));
				if(null != newInRecords && !newInRecords.isEmpty()) {
					List<String> toolCodes = newInRecords.stream().map(ToolInWarehouseRecord::getToolCode).
							collect(Collectors.toList());
					List<String> existCodes = toolMapper.listToolsByCodes(toolCodes);
					if(null != existCodes && !existCodes.isEmpty()) {
						List<ToolInWarehouseRecord> needDeletes = new ArrayList<ToolInWarehouseRecord>();
						newInRecords.stream().forEach(record->{
							if(existCodes.contains(record.getToolCode())) {
								needDeletes.add(record);
								record.setStatus(1);
								toolInWarehouseRecordMapper.updateById(record);
							}
						});
						toolCodes.removeAll(existCodes);
						newInRecords.removeAll(needDeletes);
					}
					//在30分钟之内先不处理
					Calendar c = Calendar.getInstance();
					c.add(Calendar.MINUTE, -30);
					
					if(master.getCreateTime().compareTo(c.getTime()) < 0) {
						master.setStatus(-1);
					}
					
					//如果还有未入库的工器具编号，检查是否已在柜子中
					if(!toolCodes.isEmpty()) {
						List<ToolModel> tools = new ArrayList<ToolModel>();
						List<String> inDevices = toolMapper.queryAllCodesForDevice();
						newInRecords.stream().forEach(record->{
							if(inDevices.contains(record.getToolCode())) {
								String deviceId = toolInWarehouseMasterMapper.selectInWarehouseDeviceIdByToolCode(record.getToolCode());
								ToolModel tool = toolMapper.selectById(record.getToolId());
								tool.setDeviceId(deviceId);
								tool.setIsBind(0);
								tool.setMaintainUserId(record.getUserId());
								tool.setOldCode(record.getToolOldCode());
								tool.setName(record.getToolName());
								tool.setRfidTid(record.getTid());
								toolMapper.updateById(tool);
								tools.add(tool);
								record.setStatus(1);
								record.setDeviceId(deviceId);
								record.setInWarehouseTime(new Date());
								toolCodes.remove(record.getToolCode());
								toolInWarehouseRecordMapper.updateById(record);
								
//								//生成检验台账
//								ToolInspectInDetail inspectDetail = new ToolInspectInDetail();
//								inspectDetail.setDeviceId(deviceId);
//								inspectDetail.setInspectTime(record.getInspectDate());
//								inspectDetail.setToolId(tool.getId());
//								inspectDetail.setMasterId("-1");
//								inspectInDetailMapper.insert(inspectDetail);
							}
						});
						if(toolCodes.isEmpty()) {
							master.setStatus(1);
						}
						//----生产需要发送的数据
						//发送工器具信息
						//commonSendInfo.sendToolInfoToMaster(tools);
						//发送新增台账
						//masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getNewToolRecordApi(), 
						//		newToolSchemas, ApiResult.class);
					}else {
						master.setStatus(1);
					}
					toolInWarehouseMasterMapper.updateById(master);
				}else {
					master.setStatus(-1);
					newInRecords = toolInWarehouseRecordMapper.selectList(
							new Condition<ToolInWarehouseRecord>().eq("master_id", master.getId()).eq("status", 0));
					if(null != newInRecords && !newInRecords.isEmpty()) {
						newInRecords.stream().forEach(record->{
							record.setStatus(-1);
							toolInWarehouseRecordMapper.updateById(record);
						});
					}
					toolInWarehouseMasterMapper.updateById(master);
				}
			});
		}
	}
	
	/**
	 * 
	 * @description  处理领取未完成的数据
	 * @auther 韩兵
	 * @Date 2020年8月14日
	 * @return void
	 */
	public void handlerBorrowNoDone() {
		@SuppressWarnings("unchecked")
		List<ToolBorrowMaster> hasNoDoneMasters = toolBorrowMasterMapper.selectList(
				new Condition<ToolBorrowMaster>().eq("status", 0));
		if(null != hasNoDoneMasters && !hasNoDoneMasters.isEmpty()) {
			hasNoDoneMasters.stream().forEach(master->{
				@SuppressWarnings("unchecked")
				List<ToolBorrowDetail> details = toolBorrowDetailMapper.selectList(
						new Condition<ToolBorrowDetail>().eq("master_id", master.getId()));
				List<BorrowReturnRecordSchema> masterList = new ArrayList<BorrowReturnRecordSchema>();
				if(null != details && !details.isEmpty()) {
					List<String> inDevices = toolMapper.queryAllCodesForDevice();
					List<String> hasNoDevices = new ArrayList<String>();
					details.stream().forEach(detail->{
						ToolModel tool = toolMapper.selectById(detail.getToolId());
						if(null != tool) {
							if(inDevices.contains(tool.getCode())) {
								toolBorrowDetailMapper.deleteById(detail.getId());
							}else {
								hasNoDevices.add(detail.getId());
							}
						}
					});
					if(!hasNoDevices.isEmpty()) {
						master.setStatus(1);
						@SuppressWarnings("unchecked")
						List<ToolBorrowDetail> detailses = toolBorrowDetailMapper.selectList(
								new Condition<ToolBorrowDetail>().eq("master_id", master.getId()));
						if(null != detailses && !detailses.isEmpty()) {
							detailses.stream().forEach(vo->{
								try {
									BorrowReturnRecordSchema masterSchema = new BorrowReturnRecordSchema();
									ToolModel tool = toolMapper.selectById(vo.getToolId());
									DeviceModel device = deviceMapper.selectById(vo.getDeviceId());
									masterSchema.setDeviceCode(device.getCode());
									masterSchema.setEpc(tool.getCode());
									masterSchema.setOperateDate(DateUtils.getInstance().getDateStr(vo.getCreateTime(), DateUtils.getInstance().SDF_HH));
									masterSchema.setOperateType(ToolBorrowReturnRecord.TYPE_BORROW);
									masterSchema.setOperateUserId(master.getUserId());
									masterList.add(masterSchema);
								}catch(Exception e) {
									log.error("发送领使用记录到主站异常：{}",e);
								}
							});
							//发送信息到主站
							if(!masterList.isEmpty()) {
								//masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getBorrowReturnRecordApi(), 
								//		masterList, ApiResult.class);
							}
						}
						
						//更新工器具状态
						toolMapper.updateToolStatus(hasNoDevices, 0, 1);
					}else {
						master.setStatus(-1);
					}
					toolBorrowMasterMapper.updateById(master);
				}
				master.setStatus(-1);
				toolBorrowMasterMapper.updateById(master);
			});
		}
	}
	
	/**
	 * 
	 * @description 处理归还未完成的数据
	 * @auther 韩兵
	 * @Date 2020年8月14日
	 * @return void
	 */
	@Transactional
	public void handlerReturnNoDone() {
		@SuppressWarnings("unchecked")
		List<ToolReturnMaster> masters = toolReturnMasterMapper.selectList(
				new Condition<>().eq("status", 0));
		if(null != masters && !masters.isEmpty()) {
			masters.stream().forEach(master->{
				@SuppressWarnings("unchecked")
				List<ToolReturnDetail> details = toolReturnDetailMapper.selectList(
						new Condition<ToolReturnDetail>().eq("master_id", master.getId()));
				if(null != details && !details.isEmpty()) {
					List<String> hasInDevices = new ArrayList<String>();
					List<String> inDevices = toolMapper.queryAllCodesForDevice();
					List<ToolReturnDetail> needDelete = new ArrayList<ToolReturnDetail>();
					details.stream().forEach(detail->{
						ToolModel tool = toolMapper.selectById(detail.getToolId());
						if(null != tool) {
							if(!inDevices.contains(tool.getCode())) {
								needDelete.add(detail);
								toolReturnDetailMapper.deleteById(detail.getId());
							}else {
								hasInDevices.add(tool.getId());
							}
						}
					});
					if(!needDelete.isEmpty()) {
						details.removeAll(needDelete);
					}
					if(!hasInDevices.isEmpty()) {
						//查询借的记录，并且将借的记录更新为已归还
						List<ToolBorrowDetail> borrowDetails = toolBorrowMapper.selectWaitUpdateBorrowDetails(hasInDevices);
						if(null != borrowDetails && !borrowDetails.isEmpty()) {
							for(ToolBorrowDetail borrowDetail : borrowDetails) {
								for(ToolReturnDetail returnDetail : details) {
									if(borrowDetail.getToolId().equals(returnDetail.getToolId())) {
										borrowDetail.setHasReturn(1);
										borrowDetail.setLastUpdateTime(new Date());
										borrowDetail.setReturnDeviceId(returnDetail.getDeviceId());
										borrowDetail.setReturnTime(new Date());
										borrowDetail.setReturnUserId(master.getUserId());
										toolBorrowDetailMapper.updateById(borrowDetail);
									}
								}
							}
						}
						if(!details.isEmpty()) {
							List<BorrowReturnRecordSchema> masterList = new ArrayList<BorrowReturnRecordSchema>();
							details.stream().forEach(detail->{
								ToolBorrowReturnRecord record = new ToolBorrowReturnRecord();
								record.setCreateTime(new Date());
								record.setDeviceId(detail.getDeviceId());
								record.setOperatorUserId(master.getUserId());
								record.setToolId(detail.getToolId());
								record.setType(ToolBorrowReturnRecord.TYPE_RETURN);
								toolBorrowReturnRecordMapper.insert(record);
								
								try {
									BorrowReturnRecordSchema masterSchema = new BorrowReturnRecordSchema();
									ToolModel tool = toolMapper.selectById(detail.getToolId());
									DeviceModel device = deviceMapper.selectById(detail.getDeviceId());
									masterSchema.setDeviceCode(device.getCode());
									masterSchema.setEpc(tool.getCode());
									masterSchema.setOperateDate(DateUtils.getInstance().getDateStr(record.getCreateTime(), DateUtils.getInstance().SDF_HH));
									masterSchema.setOperateType(ToolBorrowReturnRecord.TYPE_RETURN);
									masterSchema.setOperateUserId(master.getUserId());
									masterList.add(masterSchema);
								}catch(Exception e) {
									log.error("发送领使用记录到主站异常：{}",e);
								}
							});
							
							//发送信息到主站
							if(!masterList.isEmpty()) {
								//masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getBorrowReturnRecordApi(), 
								//		masterList, ApiResult.class);
							}
						}
						
						//将借据更新为已归还
						List<String> toolIds = details.stream().map(ToolReturnDetail::getToolId).collect(Collectors.toList());
						toolBorrowMapper.updateBorrowToReturn(toolIds);
						//更新工器具状态
						toolMapper.updateToolStatus(toolIds, 2, null);
					}
					master.setStatus(1);
					toolReturnMasterMapper.updateById(master);
				}else {
					master.setStatus(-1);
					toolReturnMasterMapper.updateById(master);
				}
			});
		}
	}
	
	/**
	 * 
	 * @description 处理检验出库未完成的数据
	 * @auther 韩兵
	 * @Date 2020年8月14日
	 * @return void
	 */
	public void handlerInspectOutNoDone() {
		@SuppressWarnings("unchecked")
		List<ToolInspectMaster> inspectMaster = inspectMasterMapper.selectList(
				new Condition<ToolInspectMaster>().eq("status", 0));
		if(null != inspectMaster && !inspectMaster.isEmpty()) {
			inspectMaster.stream().forEach(master->{
				@SuppressWarnings("unchecked")
				List<ToolInspectDetail> details = inspectDetailMapper.selectList(
						new Condition<ToolInspectDetail>().eq("master_id", master.getId()));
				if(null != details && !details.isEmpty()) {
					List<String> inDevices = toolMapper.queryAllCodesForDevice();
					List<String> hasNoDevices = new ArrayList<String>();
					List<ToolInspectDetail> needDelete = new ArrayList<ToolInspectDetail>();
					details.stream().forEach(detail->{
						ToolModel tool = toolMapper.selectById(detail.getToolId());
						if(null != tool) {
							if(inDevices.contains(tool.getCode())) {
								inspectDetailMapper.deleteById(detail.getId());
								needDelete.add(detail);
							}else {
								hasNoDevices.add(detail.getId());
							}
						}
					});
					if(!needDelete.isEmpty()) {
						details.removeAll(needDelete);
					}
					if(!hasNoDevices.isEmpty()) {
						master.setStatus(1);
						if(null != details && !details.isEmpty()) {
							List<String> rfIds = details.stream().map(ToolInspectDetail::getToolId).collect(Collectors.toList());
							//更新工器具状态
							toolMapper.updateToolStatus(rfIds, 1, null);
						}
					}else {
						master.setStatus(-1);
					}
					inspectMasterMapper.updateById(master);
				}else {
					master.setStatus(-1);
					inspectMasterMapper.updateById(master);
				}
			});
		}
	}
	
	/**
	 * 
	 * @description 处理检验入库未完成的数据
	 * @auther 韩兵
	 * @Date 2020年8月14日
	 * @return void
	 */
	public void handlerInspectInNoDone() {
		@SuppressWarnings("unchecked")
		List<ToolInspectInMaster> inspectMaster = inspectInMasterMapper.selectList(
				new Condition<ToolInspectInMaster>().eq("status", 0));
		if(null != inspectMaster && !inspectMaster.isEmpty()) {
			inspectMaster.stream().forEach(master->{
				@SuppressWarnings("unchecked")
				List<ToolInspectInDetail> details = inspectInDetailMapper.selectList(
						new Condition<ToolInspectInDetail>().eq("master_id", master.getId()));
				if(null != details && !details.isEmpty()) {
					List<String> inDevices = toolMapper.queryAllCodesForDevice();
					List<String> hasNoDevices = new ArrayList<String>();
					List<ToolInspectInDetail> needDelete = new ArrayList<ToolInspectInDetail>();
					List<InspectRecordSchema> records = new ArrayList<InspectRecordSchema>();
					details.stream().forEach(detail->{
						ToolModel tool = toolMapper.selectById(detail.getToolId());
						if(null != tool) {
							if(inDevices.contains(tool.getCode())) {
								hasNoDevices.add(detail.getId());
								try {
									InspectRecordSchema record = new InspectRecordSchema();
									record.setEpc(tool.getCode());
									if(null != detail.getInspectTime()) {
										record.setInspectDate(DateUtils.getInstance().getDateStr(detail.getInspectTime(), DateUtils.getInstance().SDF_HH));
									}
									records.add(record);
								}catch(Exception e) {
									log.error("组装检验数据异常",e);
								}
							}else {
								inspectDetailMapper.deleteById(detail.getId());
								needDelete.add(detail);
							}
						}
					});
					
					if(!needDelete.isEmpty()) {
						details.removeAll(needDelete);
					}
					
					if(!hasNoDevices.isEmpty()) {
						master.setStatus(1);
						if(null != details && !details.isEmpty()) {
							List<String> rfIds = details.stream().map(ToolInspectInDetail::getToolId).collect(Collectors.toList());
							//更新工器具状态
							toolMapper.updateToolStatus(rfIds, 2, null);
						}
					}else {
						master.setStatus(-1);
					}
					inspectInMasterMapper.updateById(master);
					//发送检验数据到主站
					if(!records.isEmpty()) {
						//masterConfig.sendMsgToMaster(masterConfig.getMasterApiUrl()+masterConfig.getInspectRecordApi(), 
						//		records, ApiResult.class);
					}
				}else {
					master.setStatus(-1);
					inspectInMasterMapper.updateById(master);
				}
			});
		}
	}
	
	/**
	 * 
	 * @description  开启打印机
	 * @auther 韩兵
	 * @Date 2020年11月4日
	 * @return void
	 */
	public void printStart() {
		try {
			restBiz.postForEntity(appConfig.getCommunicationApiUrl()+
					appConfig.getSendPrintStart(),
					null,Object.class);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
	}
	
	/**
	 *  发送打印
	 * @description
	 * @param code
	 * @auther 韩兵
	 * @Date 2020年8月20日
	 * @return void
	 */
	@SuppressWarnings("unchecked")
	public void printCode(String code) {
		if(!StringUtils.isBlank(code)) {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("code", code);
			try {
				restBiz.postForEntity(appConfig.getCommunicationApiUrl()+
						appConfig.getSendPrintContent(),
						jsonObject,Object.class);
			} catch(Exception e) {
				log.error("下发命令",e);
			}
		}
	}
	
	/**
	 * 
	 * @description  关闭打印机
	 * @auther 韩兵
	 * @Date 2020年8月20日
	 * @return void
	 */
	public void printClose() {
		try {
			restBiz.postForEntity(appConfig.getCommunicationApiUrl()+
					appConfig.getSendPrintClose(),
					null,Object.class);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
	}
	
	/**
	 * 
	 * @description 计算两个点的坐标距离
	 * @param lng
	 * @param lat
	 * @param lngOther
	 * @param latOther
	 * @return
	 * @auther 韩兵
	 * @Date 2020年8月27日
	 * @return Double
	 */
	public static Double calcutLocation(Double lng, Double lat, Double lngOther, Double latOther) {
		double lon1 = (Math.PI / 180) * lng;
        double lon2 = (Math.PI / 180) * lngOther;
        double lat1 = (Math.PI / 180) * lat;
        double lat2 = (Math.PI / 180) * latOther;
        
        return Math.acos(Math.sin(lat1) * Math.sin(lat2) + 
        		Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * EARTH_RADIUS;
	}
	
	/**
	 * 
	 * @description 生成网格的数据
	 * @auther 韩兵
	 * @Date 2020年8月28日
	 * @return void
	 */
	public void produceCornerSeri() {
		List<StationLacation> stations = stationLocationMapper.selectList(new Condition<StationLacation>());
		if(null == stations || stations.isEmpty()) {
			String cornerSeri = appConfig.getGrisCornerSeri();
			int xLenght = appConfig.getGrisXlenght();
			int yLenght = appConfig.getGrisYLenght();
			String[] cornerSeriArray = cornerSeri.split(";");
			String corner0 = cornerSeriArray[0];
			String corner1 = cornerSeriArray[1];
			//String corner2 = cornerSeriArray[2];
			String corner3 = cornerSeriArray[3];
			
			BigDecimal startX = new BigDecimal(corner0.split(",")[0]);
			BigDecimal endX = new BigDecimal(corner3.split(",")[0]);
			BigDecimal startY = new BigDecimal(corner0.split(",")[1]);
			BigDecimal endY = new BigDecimal(corner1.split(",")[1]);
			
			//double distanceX = endX - startX;
			BigDecimal stepX = endX.subtract(startX).divide(new BigDecimal(xLenght));
			//double distanceY = endY - startY;
			BigDecimal stepY = endY.subtract(startY).divide(new BigDecimal(yLenght));
			
			StringBuffer location = new StringBuffer();
			for(int i=0;i<xLenght;i++) {
				BigDecimal xLocation = startX.add(stepX.multiply(new BigDecimal(i))).setScale(6, RoundingMode.HALF_UP);
				for(int j=0;j<yLenght;j++) {
					BigDecimal yLocation = startY.add(stepY.multiply(new BigDecimal(j))).setScale(6, RoundingMode.HALF_UP);
					location.append(xLocation+","+yLocation).append(";");
				}
			}
			
			if(null != location && location.length() > 0) {
				String locationStr = location.substring(0, location.length()-1);
				StationLacation station = new StationLacation();
				station.setLocation(locationStr);
				//stationLocationMapper.insert(station);
			}
		}
	}
	
	public void produceCornerSeri1() {
		//List<StationLacation> stations = stationLocationMapper.selectList(new Condition<StationLacation>());
		//if(null == stations || stations.isEmpty()) {
			String cornerSeri = appConfig.getGrisCornerSeri();
			//int xLenght = appConfig.getGrisXlenght();
			//int yLenght = appConfig.getGrisYLenght();
			int xLenght = 30;
			int yLenght = 30;
			String[] cornerSeriArray = cornerSeri.split(";");
			String corner0 = cornerSeriArray[0];
			String corner1 = cornerSeriArray[1];
			//String corner2 = cornerSeriArray[2];
			String corner3 = cornerSeriArray[3];
			
			BigDecimal startX = new BigDecimal(corner0.split(",")[0]);
			BigDecimal endX = new BigDecimal(corner3.split(",")[0]);
			BigDecimal startY = new BigDecimal(corner0.split(",")[1]);
			BigDecimal endY = new BigDecimal(corner1.split(",")[1]);
			
			//double distanceX = endX - startX;
			BigDecimal stepX = endX.subtract(startX).divide(new BigDecimal(xLenght),6, RoundingMode.HALF_UP);
			//double distanceY = endY - startY;
			BigDecimal stepY = endY.subtract(startY).divide(new BigDecimal(yLenght),6, RoundingMode.HALF_UP);
			
			//BigDecimal stepX1 = endX.subtract(startX).divide(new BigDecimal(xLenght*3),6,BigDecimal.ROUND_HALF_UP);
			//double distanceY = endY - startY;
			//BigDecimal stepY1 = endY.subtract(startY).divide(new BigDecimal(yLenght),6,BigDecimal.ROUND_HALF_UP);
			stepX = stepX.add(BigDecimal.valueOf(0.0000024));
			StringBuffer location = new StringBuffer();
			List<String> localtiona = new ArrayList<String>();
			for(int i=0;i<xLenght;i++) {
				BigDecimal xLocation = startX.add(stepX.multiply(new BigDecimal(i))).setScale(6, RoundingMode.HALF_UP);
				//xLocation = xLocation.add(stepX1.multiply(new BigDecimal(i)));
				for(int j=0;j<yLenght;j++) {
					BigDecimal yLocation = startY.add(stepY.multiply(new BigDecimal(j))).setScale(6, RoundingMode.HALF_UP);
					//yLocation = yLocation.subtract(stepY1.multiply(new BigDecimal(i*j)));
					localtiona.add(xLocation+","+yLocation);
					//location.append(xLocation+","+yLocation).append(";");
				}
			}
			for(int i=0;i<localtiona.size();i++) {
				String[] v = localtiona.get(i).split(",");
				BigDecimal x = new BigDecimal(v[0]).add(BigDecimal.valueOf(0.000028d*(i%30d))).setScale(6, RoundingMode.HALF_UP);
				BigDecimal y = new BigDecimal(v[1]).subtract(BigDecimal.valueOf(0.000022d*(i/30d))).setScale(6, RoundingMode.HALF_UP);
				//BigDecimal x = new BigDecimal(v[0]).add(stepX1.multiply(new BigDecimal(xLenght)));
				//BigDecimal y = new BigDecimal(v[1]).subtract(stepY1.multiply(new BigDecimal(yLenght)));
				//location.append(x+","+y).append(";");
				location.append(x+","+y).append(";");
			}
			
			if(null != location && location.length() > 0) {
				String locationStr = location.substring(0, location.length()-1);
				StationLacation station = new StationLacation();
				station.setLocation(locationStr);
				//stationLocationMapper.insert(station);
				List<String> coooos = Arrays.asList(locationStr.split(";"));
				Collections.reverse(coooos);
			}
		//}
	}
	
	@SuppressWarnings("rawtypes")
	public synchronized ApiResult acquireBorrowPlanMasterId(String img) {
		if(StringUtils.isBlank(img)) {
    		return ApiResult.fail();
    	}
		img = img.replaceAll("\\\\", "/");
		List<ToolBorrowPlanMaster> masters = toolBorrowPlanMasterMapper.selectList(new Condition<ToolBorrowPlanMaster>());
		//去调接口，判断选取的是哪个计划
		if(null != masters && !masters.isEmpty()) {
			StringBuffer voiceTip = new StringBuffer();
			//接口调用
			//默认是1
			String masterId = null;
			ResponseEntity<?> entity = null;
			String scanName = null;
			String scanCode = null;
			Map<String,String> param = new HashMap<String,String>();
			param.put("img", img);
			log.info("--------------------------orc图片路径："+img);
			
			try {
				entity = restBiz.postForEntityOhter(appConfig.getCommunicationApiUrl()+
						appConfig.getSendOperateTaskScan(),
						param,String.class,param);
				if(null != entity && entity.getStatusCode() == HttpStatus.OK){
					scanName = (String)entity.getBody();
					log.info("-------------------------识别内容："+scanName);
				}
			} catch(Exception e) {
				log.error("调用任务扫描api异常",e);
			}
			
			if(!StringUtils.isBlank(scanName)) {
				for(ToolBorrowPlanMaster master : masters) {
					String keyNames = master.getKeyName();
					if(!StringUtils.isBlank(keyNames)) {
						String[] keyNameArray = keyNames.split(",");
						Boolean find = true;
						for(String keyName : keyNameArray) {
							if (!scanName.contains(keyName)) {
								find = false;
								break;
							}
						}
						if(find) {
							masterId = master.getId();
							log.info("------------------找到的masterId:"+masterId);
							List<BorrowPlanVO> result = toolBorrowMapper.selectBorrowPlanByMasterId(masterId, null);
							//设置亮灯的柜子
							if(null != result && !result.isEmpty()) {
								Map<String,BigDecimal> needBorrow = 
										result.stream().collect(Collectors.toMap(p->p.getModelId(), p->p.getPlanQuatity()));
								List<DeviceToolTypeVO> deviceTools = this.checkToolInDeviceNew(needBorrow);
								if(null != deviceTools && !deviceTools.isEmpty()) {
									//设置语音提示
									voiceTip.append("推荐您到");
									deviceTools.stream().forEach(vo->{
										voiceTip.append(vo.getDeviceName()+"号柜领取"+vo.getToolName()+vo.getTypeModel());
									});
									//设置亮灯的柜子
									this.sendLightCommand(deviceTools.stream().map(DeviceToolTypeVO::getDeviceCode).collect(Collectors.toList()), 1);
								}
							}
							this.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2000.getValue());
							//copy识别的orc图片
							String ocrImg = System.currentTimeMillis()+".jpg";
							this.transImg(img, ocrImg);
							CacheOcrModel cache = new CacheOcrModel();
							cache.setBorrowPlanMasterId(masterId);
							cache.setOcrImg(ocrImg);
							cache.setOcrName(replaceOrcContent(scanName));
							cache.setOcrCode(scanCode);
							CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_BORROW_OCR_SCAN.getValue(), cache);
							this.deleteOrcImg(img);
							return ApiResult.success(voiceTip);
						}
					}
				}
				String ocrImg = System.currentTimeMillis()+".jpg";
				this.transImg(img, ocrImg);
				CacheOcrModel cache = new CacheOcrModel();
				cache.setBorrowPlanMasterId(masterId);
				cache.setOcrImg(ocrImg);
				cache.setOcrName(replaceOrcContent(scanName));
				cache.setOcrCode(scanCode);
				CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_BORROW_OCR_SCAN.getValue(), cache);
				return ApiResult.success();
			}
			this.deleteOrcImg(img);
			return ApiResult.fail("识别失败,您可选择手动录入操作任务");
		}
		this.deleteOrcImg(img);
		return ApiResult.fail("识别失败,您可选择手动录入操作任务");
	}
	
	public String replaceOrcContent(String content) {
		if(StringUtils.isBlank(content)) {
			return "";
		}
		content = StringEscapeUtils.unescapeJava(content);
		content = StringEscapeUtils.unescapeHtml(content);
		content = com.sihan.framework.etm.common.util.StringUtils.StringFilter(content);
		String pattern = "kv|ky";
		Pattern p = Pattern.compile(pattern,Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(content);
		return m.replaceAll("kV").trim();
	}
	
	public void deleteOrcImg(String filePath) {
		File file = new File(filePath);
		if(file.exists()) {
			try {
				if(!file.delete()) {
					log.error("删除文件失败");
				}
			}catch(Exception e) {
				log.error("删除orc图片异常：",e);
			}
		}
	}
	
	public ApiResult<?> skipStep(Boolean openDoor,String taskName,String taskId,
			String startTime,String endTime,String taskCode){
		if(openDoor) {
			if(!StringUtils.isBlank(taskId)) {
				CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_BORROW_TASK_ID.getValue(), 
						taskId);
			}else {
				BorrowToolTaskDTO vo = new BorrowToolTaskDTO();
				vo.setTaskName(taskName);
				vo.setTaskCode(taskCode);
				vo.setStartTime(startTime);
				vo.setEndTime(endTime);
				CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_BORROW_REASON.getValue(), 
					vo);
			}
			this.sendCommandToDevice(MqttSendCommandFunc.COMMAND_2000.getValue());
		}
		return ApiResult.success();
	}
	
	//转移图片
	public void transImg(String originImg,String newImgName) {
		File file = new File(originImg);
		FileInputStream fis = null;
		if(file.exists()) {
			try (FileOutputStream fos = new FileOutputStream(new File(appConfig.getRootPath()+"/"+FormatImgPre.PRE_ORC.getValue()+newImgName))){
				fis = new FileInputStream(file);
				byte[] read = new byte[1024];
	            int len = 0;
	            while((len = fis.read(read))!= -1){
	                fos.write(read,0,len);
	            }
			} catch (FileNotFoundException e) {
				log.error("扫描任务转移图片异常：{}",e);
			} catch (IOException e) {
				log.error("扫描任务转移图片异常：{}",e);
			}finally {
				if(null != fis) {
					try{
						fis.close();
			            if(!file.delete()) {
			            	log.error("删除文件失败");
			            }
					}catch(Exception e) {
						log.error("关闭文件异常",e);
					}
				}
			}
		}
	}

	public String checkValidatedUserId() {
		String userId = (String)CacheOperatorInfo.getMapValue(CacheKeyName.VALIDATED_USER_ID.getValue(), null);
		return userId;
	}
	
	
	public void startToolTid() {
		CacheOperatorInfo.setMapValue(CacheKeyName.READER_LOG.getValue(), "4");
		CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), 
				CacheKeyName.READER_CODE_LIST.getValue());
		log.info("准备发送开启扫描------------------------------------------------");
		doing = true;
		this.sendIvgScanStartCommand();
	}
	
	public void setToolTid() {
		while(doing) {
			String code = (String)CacheOperatorInfo.getMapValue(CacheKeyName.READER_CODE_LIST.getValue(), 
					CacheKeyName.READER_CODE_LIST.getValue());
			String tid = (String)CacheOperatorInfo.getMapValue(CacheKeyName.TID_VALUE.getValue(), 
					CacheKeyName.TID_VALUE.getValue());
			if(!StringUtils.isBlank(code) && !code.equals(CacheKeyName.READER_CODE_LIST.getValue())) {
				@SuppressWarnings("unchecked")
				ToolModel tool = toolMapper.selectOne(new Condition<ToolModel>().eq("code", code));
				if(tool != null) {
					tool.setTid(tid);
					log.info("-----------------------tid:"+tid+"---------------------");
					toolMapper.updateById(tool);
				}
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_LOG.getValue(), "4");
				CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), 
						CacheKeyName.READER_CODE_LIST.getValue());
				CacheOperatorInfo.setMapValue(CacheKeyName.TID_VALUE.getValue(), 
						CacheKeyName.TID_VALUE.getValue());
				log.info("---------------------------------设置  TID 成功----------------------");
			}
		}
	}
	
	public void sendSetDeviceConfig(Integer commandCode,String deviceCode,Integer readChannel) {
		SetDeviceConfigDTO dto = new SetDeviceConfigDTO();
		dto.setCode(deviceCode);
		dto.setMqtt_broker(appConfig.getMqttTcp());
		dto.setMqtt_password(appConfig.getMqttPassword());
		dto.setMqtt_username(appConfig.getMqttUsername());
		dto.setRead_channel(readChannel);
		dto.setRead_speed(appConfig.getReadSpeed());
		dto.setTag_url(appConfig.getDeviceImgAddr());
		dto.setCommand(commandCode);
		dto.setTrade_no(System.currentTimeMillis()+"");
		BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
		req.setTopic("command/"+deviceCode);
		try {
			req.setPayload(JsonUtils.toJsonString(dto));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			log.info("下发柜子命令："+JsonUtils.toJsonString(req));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			//缓存交易号
			CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
					dto.getTrade_no());
			restBiz.postForEntity(
					appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
		} catch(Exception e) {
			log.error("下发命令",e);
		}
	}
	
	/**
	 * 
	 * @description  单个柜子的下发命令
	 * @param commandCode
	 * @param deviceCode
	 * @auther 韩兵
	 * @Date 2020年10月21日
	 * @return void
	 */
	public void sendDeviceCommand(Integer commandCode, String deviceCode) {
		ExternalJsonObjectDTO dto = new ExternalJsonObjectDTO();
		dto.setCommand(commandCode);
		dto.setTrade_no(System.currentTimeMillis()+"");
		BoxDeviceInfoDTO req = new BoxDeviceInfoDTO();
		req.setTopic("command/"+deviceCode);
		try {
			req.setPayload(JsonUtils.toJsonString(dto));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			log.info("下发柜子命令："+JsonUtils.toJsonString(req));
		} catch (IOException e) {
			log.error("下发柜子命令json报错", e);
		}
		try {
			//缓存交易号
			CacheOperatorInfo.setMapValue(CacheKeyName.CACHE_DEVICE_TRADE_NO.getValue(), 
					dto.getTrade_no());
			restBiz.postForEntity(
					appConfig.getCommunicationApiUrl()+appConfig.getSendCommandApi(),req,Object.class);
		} catch(Exception e) {
			log.info("下发命令",e);
		}
	}
	
	public void endToolTid() {
		CacheOperatorInfo.setMapValue(CacheKeyName.READER_LOG.getValue(), "0");
		CacheOperatorInfo.setMapValue(CacheKeyName.READER_CODE_LIST.getValue(), 
				CacheKeyName.READER_CODE_LIST.getValue());
		log.info("准备发送关闭扫描------------------------------------------------");
		doing = false;
		this.sendIvgScanStopCommand();
	}
	
	/**
	 * @description
	 * @param orgId
	 * @auther 韩兵
	 * @Date 2021年8月24日
	 * @return void
	 */
	public void setUserOrgIds(String userId,String orgId) {
		StringBuffer orgIds = new StringBuffer();
		orgIds.append(orgId+",");

		User user = userMapper.selectById(userId);
		if ("admin".equals(user.getUsername())){
			List<String> strings = orgMapper.selectAllOrgId();
			String join = StringUtils.join(strings, ",");
			CacheOperatorInfo.setMapValue(userId, join);
			return;
		}else {
			setChildOrg(orgId,orgIds);
		}
		CacheOperatorInfo.setMapValue(userId, orgIds.toString());
	}


	public void setUserOrgIds(String userId) {
		User user = userMapper.selectById(userId);
		StringBuffer orgIds = new StringBuffer();
		orgIds.append(user.getOrgId()).append(",");

		if ("admin".equals(user.getUsername())){
			List<String> strings = orgMapper.selectAllOrgId();
			String join = StringUtils.join(strings, ",");
			CacheOperatorInfo.setMapValue(userId, join);
			return;
		}else {
			setChildOrg(user.getOrgId(),orgIds);
		}
		CacheOperatorInfo.setMapValue(userId, orgIds.toString());
	}
	
//	private void setChildOrg(String orgId,StringBuffer orgIds) {
//
//		List<String> childs = orgMapper.selectAllByUserId(orgId);
//
//
//		orgIds.append(StringUtils.join(childs, ",")).append(",");
//	}


	private void setChildOrg(String orgId,StringBuffer orgIds) {
		List<String> childs = commonMapper.selectOrgByParentId(orgId);
		if(null != childs && !childs.isEmpty()) {
			orgIds.append(StringUtils.join(childs, ",")).append(",");
			childs.stream().forEach(child->{
				setChildOrg(child,orgIds);
			});
		}
	}
	
	public static void main(String[] args) {
		//104.041895,30.585171
		//104.059358,30.556222
		System.out.println(calcutLocation(104.059358,30.556222,104.041895,30.585171));
	}


}
